home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
c_dates.zip
/
C_DATES.C
next >
Wrap
Text File
|
1987-08-04
|
14KB
|
377 lines
/************************************************************************/
/* (c) 1987 by James N. Seed, Dallas, TX - all rights reserved. */
/* */
/* Permission is granted to freely distribute and use this document */
/* for whatever purpose provided that: */
/* */
/* A) this copyright notice, in its entirety, including the author's */
/* name (above) is not removed or altered, and */
/* */
/* B) it, and/or any or all of the algorithms it contains, is not */
/* sold, distributed, or used in any form, FOR MONETARY PROFIT, */
/* without the express written consent of the author, named above. */
/************************************************************************/
/************************************************************************/
/* All of these routines were written entirely in machine independant, */
/* compiler independant, standard ( ANSI ) "C" language. */
/* */
/* The only exceptions to the machine independance of the source occur */
/* in "jtog" and "fulldte", because they assume the usage of the ASCII */
/* character set. */
/************************************************************************/
/************************************************************************/
/* Notes: For those of you that don't already know, a "julian" date */
/* ===== is simply the number of days that has transpired since */
/* some arbitrary point in time. For these routines, that */
/* arbitrary point in time is 01/00/0000, or the 0th day A.D. */
/* A "gregorian" date is simply a date expressed in terms of */
/* the month, day, and year, which is what we use today. */
/* */
/* The name "julian" comes from the creator of the original */
/* concept, Julius Caesar, and I think the name "gregorian" */
/* comes from Pope Gregory, who sanctified the continued use */
/* of the original Pagan concept, although I'm not sure... */
/* */
/* All of these routines assume that year 0000 is a leap year. */
/* */
/* In the interest of portability, I have not declared any */
/* "unsigned long" variable types, because some compilers do */
/* not support it. The "docs in the box" for each routine, */
/* however, specify which long integers should be unsigned, */
/* so you can go ahead and change the source to reflect this */
/* if you like. It will only make a difference if you are */
/* working with HUGE date numbers ( ie: past year 9999 ) or */
/* in the ( unlikely? ) event that you erroneously input a */
/* negative julian date. ( a definite no no ) */
/************************************************************************/
/************************************************************************/
/* *** gtoj.c *** */
/* */
/* This function converts a gregorian date, in the ( month, day, year ) */
/* format, into its respective julian, or day number, equivalent. */
/* ( 1 = 1st day AD ) */
/* */
/* The legal input values, in their proper order, are: */
/* */
/* month = 1 to 12 ( unsigned int ) */
/* day = 1 to 31 ( unsigned int ) */
/* year = 0 to 9999 ( unsigned int ) */
/* */
/* The return value of the function is the julian day number */
/* expressed as an unsigned long integer. */
/* */
/************************************************************************/
long gtoj( m, d, y )
unsigned int m, d, y;
{
y += ( m += 9 ) / 12 + 399;
m %= 12;
return ( (long)y*365 + y/4 - y/100 + y/400 + (153*m+2)/5 + d - 146037 );
}
/************************************************************************/
/* *** jtog.c *** */
/* */
/* This function converts a julian day number ( 1 = 1st day AD ), into */
/* either a gregorian date character string, in any one of the four */
/* formats described below, or an array of three integers representing */
/* the month, day, and year, respectively, of the equivalent gregorian */
/* date. Storage for the output is provided by the calling routine. */
/* */
/* The input values, in their proper order, are: */
/* */
/* 1. the julian date to be converted, ( unsigned long ) */
/* */
/* 2. a pointer to the output array, ( char * ) */
/* */
/* 3. the format code ( described below ) */
/* specifying the desired output format. ( unsigned int ) */
/* */
/* The format codes are defined as follows: */
/* */
/* CODE - EXPLANATION - */
/* */
/* 0 - output array will hold three integers defined as: */
/* */
/* array[0] = month ( mm ) */
/* array[1] = day ( dd ) */
/* array[2] = year ( yyyy ) */
/* */
/* If this format option is used, a type cast will have to */
/* be performed on the output pointer to convert it to the */
/* appropriate pointer type. ( see example below ) */
/* */
/* 1 - output string will hold a character string in the */
/* format "mmddyy" ( minimum - char string[7] ) */
/* */
/* 2 - output string will hold a character string in the */
/* format "mmddyyyy" ( minimum - char string[9] ) */
/* */
/* 3 - output string will hold a character string in the */
/* format "mm/dd/yy" ( minimum - char string[9] ) */
/* */
/* 4 - output string will hold a character string in the */
/* format "mm/dd/yyyy" ( minimum - char string[11] ) */
/* */
/* NOTE - input of any format code not listed above will be */
/* interpreted as code 0. */
/* */
/* The function returns a character pointer to the output array. */
/* ______________________________________________________________ */
/* | *** example of integer array output *** | */
/* | | */
/* | int month, dte_array[3]; | */
/* | long julian = 548784; | */
/* | | */
/* | month = ( (int *)jtog( julian, (char *)dte_array, 0 ) )[0]; | */
/* |______________________________________________________________| */
/* */
/* WARNING - the output array pointed to must be dimensioned */
/* accordingly or a memory overwrite will occur. */
/************************************************************************/
char *jtog( julian, date, fmt )
long julian;
char *date;
unsigned int fmt;
{
int month, day, year, i;
long numdte, indx = !( fmt & 1 ) * 9900 + 100;
year = ( julian += 146037 ) * 400 / 146097;
julian -= (long)year*365 + year/4 - year/100 + year/400;
if ( !julian ) julian = 365 + !( year % 4 ), --year;
year += ( month = ( day = (int)julian * 5 - 3 ) / 153 + 2 ) / 12 - 400;
month = month % 12 + 1;
day = day % 153 / 5 + 1;
if ( fmt && fmt < 5 )
{
numdte = (long)month * 100 * indx + day * indx + year % indx;
for ( indx *= 10000, i = 0; indx > 1; ++i )
date[i] = ( fmt > 2 && ( i == 2 || i == 5 ) ) ? '/'
: (char)( numdte / ( indx /= 10 ) % 10 + 48 );
date[i] = '\0';
}
else
{
((int *)date)[0] = month;
((int *)date)[1] = day;
((int *)date)[2] = year;
}
return( date );
}
/************************************************************************/
/* *** dow.c *** */
/* */
/* This function returns the numerical day-of-week of a julian */
/* date, input as an unsigned long integer. */
/* */
/* The return value of the function is the day of the week expressed */
/* as an unsigned integer value, and is enumerated as follows: */
/* */
/* Sunday - 0 */
/* Monday - 1 Thursday - 4 */
/* Tuesday - 2 Friday - 5 */
/* Wednesday - 3 Saturday - 6 */
/* */
/************************************************************************/
int dow( julian )
long julian;
{
return( (int)( ( julian + 5 ) % 7 ) );
}
/************************************************************************/
/* *** fulldte.c *** */
/* */
/* This function converts a julian day number ( 1 = 1st day AD ), */
/* into an equivalent gregorian date descriptive phraze of the form: */
/* */
/* "Wednesday September 16, 1987" ( example ) */
/* */
/* The input values, in their proper order, are: */
/* */
/* 1. the julian date to be converted ( unsigned long ) */
/* */
/* 2. a pointer to the output character string. ( char * ) */
/* */
/* The length, in ASCII characters, of the output string is returned */
/* by the function upon completion, expressed as an unsigned integer. */
/* */
/* WARNING - the character string pointed to must be dimensioned to */
/* at least 29 characters, or a memory overwrite may occur. */
/* */
/************************************************************************/
int fulldte( julian, dtestr )
long julian;
char *dtestr;
{
static char *daynme[7] = { "Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday",
"Saturday" };
static char *mosnme[12] = { "January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December" };
static char **text[2] = { daynme, mosnme };
int i, j, k, strt, dtearr[4];
dtearr[0] = dow( julian );
jtog( julian, (char *)&dtearr[1], 0 );
--dtearr[1];
for ( i = j = k = 0; i < 2; k = 0, ++i )
{
while ( text[i][dtearr[i]][k] )
dtestr[j++] = text[i][dtearr[i]][k++];
dtestr[j++] = ' ';
}
for ( strt = 0, i = 2; i < 4; ++i )
{
for ( k = 1000; k; dtearr[i] %= k, k /= 10 )
{
if ( strt = strt || dtearr[i] / k )
dtestr[j++] = (char)( dtearr[i] / k + 48 );
}
if ( i == 2 ) dtestr[j++] = ',';
dtestr[j++] = ' ';
}
dtestr[--j] = '\0';
return( j );
}
/************************************************************************/
/* *** daycnt.c *** */
/* */
/* This function returns the number of days of the specified type that */
/* exist between the two julian dates input, expressed as an signed */
/* long integer. */
/* */
/* The input values to the function, in their proper order, are: */
/* */
/* 1. the beginning julian date ( unsigned long ) */
/* */
/* 2. the ending julian date ( unsigned long ) */
/* */
/* 3. the numerical code representing the type */
/* of days to be counted ( described below ) ( unsigned int ) */
/* */
/* The following is a list of the codes used to define the */
/* type of days that are to be counted: */
/* */
/* CODE - EXPLANATION - */
/* */
/* 0 - all days */
/* */
/* 1 - all days excluding Sundays */
/* */
/* 2 - all days excluding weekends ( Saturdays and Sundays ) */
/* */
/* NOTE - input of any code not listed above will be */
/* interpreted as code 0. */
/* */
/************************************************************************/
long daycnt( juldt1, juldt2, excl )
long juldt1, juldt2;
unsigned int excl;
{
int eff = 7 - ( excl = excl > 2 ? 0 : excl );
if ( !excl-- ) return( juldt2 - juldt1 );
if ( juldt1 > juldt2 ) return( -daycnt( juldt2, juldt1, ++excl ) );
else
{
juldt1 -= !dow( juldt1 ) + ( excl && !( dow( juldt1 ) % 6 ) );
juldt2 -= !dow( juldt2 ) + ( excl && !( dow( juldt2 ) % 6 ) );
}
return( ( juldt2 - juldt1 ) / 7 * eff +
( dow( juldt2 ) - dow( juldt1 ) + eff ) % eff );
}
/************************************************************************/
/* *** newdate.c *** */
/* */
/* This function returns a new julian date, expressed as an unsigned */
/* long integer, arrived at by adding a specified number of days of a */
/* specified type to the starting julian date input. */
/* */
/* In short, it adds days to a date to get a new date. */
/* */
/* The input values to the function, in their proper order, are: */
/* */
/* 1. the beginning julian date ( unsigned long ) */
/* */
/* 2. the number of days to be added ( signed long ) */
/* */
/* 3. the numerical code representing the type */
/* of days to be added ( described below ) ( unsigned int ) */
/* */
/* The following is a list of the codes used to define the */
/* type of days that are to be added to the start date: */
/* */
/* CODE - EXPLANATION - */
/* */
/* 0 - weekdays and weekends (all days) */
/* */
/* 1 - weekdays and Saturdays only (Sundays skipped over) */
/* */
/* 2 - weekdays only (weekends skipped over) */
/* */
/* NOTE - input of any code not listed above will be */
/* interpreted as code 0. */
/* */
/************************************************************************/
long newdate( juldte, days, incl )
long juldte, days;
unsigned int incl;
{
int eff = 7 - ( incl = incl > 2 ? 0 : incl ), rvrse = 0;
if ( !incl-- ) return( juldte + days );
if ( days < 0 )
{
rvrse = eff + 1;
juldte += !dow( juldte ) + 2 * ( incl && !( 6 - dow( juldte ) ) );
}
else juldte -= !dow( juldte ) + ( incl && !( dow( juldte ) % 6 ) );
return( juldte + days / eff * 7 + days % eff + ++incl *
( ( dow( juldte ) + days % eff - rvrse ) / ( eff + 1 ) ) );
}